<template>
    <div class="wiper">
        <Filter title="角色管理" :items="items" :model="filterModel" />
        <Table :columns="columns" :data="data" :pagination="filterModel"/>
        <Form ref="form" v-model:show="show" :rules="rules" :model="formModel" :items="formItems" :width="500">
            <template v-slot:bottom>
                <FormItem  name="menuIds" label="选择菜单">
                    <Transfer :data-source="[]" :select-all-labels="[' ', ' ']"
                              :titles="['未选择', '已选择']"
                              :render="item => item.title"
                              v-model:target-keys="targetKeys"
                    >
                        <template #children="{direction, selectedKeys, onItemSelect}">
                            <Tree v-if="direction === 'left'"
                                  :tree-data="treeData"
                                  checkable
                                  checkStrictly
                                  :checked-keys="[...targetKeys]"
                                  default-expand-all
                                  @check="
                                    (_, props) => {
                                      _onChecked(props);
                                    }
                                  "
                                  @select="
                                    (_, props) => {
                                      _onChecked(props);
                                    }
                                  "
                            />
                            <Tree v-if="direction === 'right'"
                                  :tree-data="selectedData"
                                  default-expand-all
                                  :show-line="true"
                                  :show-icon="false"
                            />
                        </template>
                    </Transfer>
                </FormItem>
            </template>
        </Form>
    </div>
</template>
<script>
    import {Tree, Transfer, FormItem} from "ant-design-vue";
    import Filter from "../../components/Filter";
    import Table from "../../components/Table";
    import Form from "../../components/Form";
    import {pager, save, remove, details} from "../../api/role";
    import {ColumnProps, RuleProps, FormProps,
        FilterItems, FormItems, FilterModelProps} from "./config";
    import {Dictionary} from "../../utils/Dictionary";
    import {menuAll} from "../../api/menu"

    export default {
        name: 'role',
        data(){
            return{
                items: FilterItems,
                data: [],
                show: false,
                formModel: FormProps,
                rules: RuleProps,
                columns: ColumnProps,
                filterModel: {
                    ...FilterModelProps,
                    onChange: (page, pageSize)=>{
                        this.filterModel.current = page;
                        this.filterModel.pageSize = pageSize;
                        this.load();
                    }
                },
                formItems: FormItems,
                treeData: [],
                targetKeys: [],
                selectedData: [],
            }
        },
        computed:{
            isDictionary(){
                return this.$store.state.dictionary
            }
        },
        watch: {
            isDictionary(data){
                this._dataRange(data);
            }
        },
        components:{
            Filter,
            Table,
            Form,
            Tree,
            Transfer,
            FormItem
        },
        mounted(){
            this.load();
            this._menuAll();
            this._dataRange(this.$store.state.dictionary);
        },
        methods: {

            /**
             * 添加方法
             */
            add(){
                this.formModel.id = "";
                this.$refs.form.resetField();
                this.targetKeys = [];
                this.selectedData = [];
                this.show = true;
            },

            /**
             * 修改方法
             */
            modify(ids){
                this.targetKeys = [];
                this.selectedData = [];
                this.show = true;
                details(ids.join(",")).then(res => {
                    this.formModel = res.data;
                    this.targetKeys = res.data.menuIds.split(",").map(item => parseInt(item));
                    this._setSelectedData()
                })
            },

            /**
             * 删除方法
             */
            delete(ids){
                return new Promise((resolve, reject) => {
                    remove(ids.join(",")).then(res => {
                        this.load();
                        return resolve(res);
                    }).catch(e => {
                        return reject(e);
                    })
                })
            },

            /**
             * 提交
             */
            submit(){
                return new Promise((resolve, reject)=> {
                    save(this.formModel).then(res => {
                        this.load();
                        return resolve(res);
                    }).catch((e)=>{
                        return reject(e)
                    })
                })
            },


            /**
             * 加载数据
             */
            load(){
                pager(this.filterModel).then(res => {
                    this.data = res.data.rows;
                    this.filterModel.total = res.data.total;
                })
            },

            /**
             * 重命名
             * @private
             */
            _rename(list, key = "id"){
                return list?.map(item => {
                    return {label: item.name, value: item[key],children: this._rename(item.children)}
                });
            },

            /**
             * 查找数据范围
             * @param data
             * @private
             */
            _dataRange(data){
                const dataRanges = data.filter(item => item.code === Dictionary.DATA_RANGE).map(item => item.children);
                this.formItems.filter(item => item.key === 'dataRange')[0].data = this._rename(dataRanges[0], "code");
            },

            /**
             * 查找所有菜单树形
             * @private
             */
            _menuAll(){
                menuAll().then(res => {
                    this.treeData =  this._treeDataRename(res.data);
                })
            },

            /**
             * 重新命名
             * @private
             */
            _treeDataRename(row){
                return row.map(item => {
                    return {key: item.id, title: item.name, children: this._treeDataRename(item.children)}
                })
            },

            _onChecked(e){
                const key = e.node.key;
                this.targetKeys.includes(key) ?
                    this.targetKeys.splice(this.targetKeys.indexOf(key), 1) :
                    this.targetKeys.push(e.node.key);
                this.selectedData = [];
                this.formModel.menuIds = this.targetKeys.join(",")
                this._setSelectedData()
            },

            /**
             * 设置选中的数据
             * @private
             */
            _setSelectedData(){
                this.treeData.forEach(item => {
                    const data = this._filterSelectedChildren(item, this.targetKeys);
                    if(data){
                        this.selectedData.push(data);
                    }
                })
            },


            /**
             * 过滤出所有选中的元素
             * @param item
             * @param selectedIds
             * @returns {{children: any}}
             * @private
             */
            _filterSelectedChildren(item, selectedIds){
                const isSelected = selectedIds.includes(item.key);
                const selectedChildren = (item.children || []).
                    map(child => this._filterSelectedChildren(child, selectedIds)).filter(Boolean);
                if(isSelected || selectedChildren.length > 0){
                    return {
                        ...item,
                        children: selectedChildren.length > 0 ? selectedChildren : undefined
                    }
                }
            }
        }
    }
</script>
<style>

</style>
